﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using Athena.Objects;

namespace Athena.Tools
{    
    public class DecorateTool : INonVisualTool
    {
        public override bool Handles(List<Type> oTypes)
        {
            bool bResult = true;
            foreach (Type t in oTypes)
            {
                bResult &= Handles(t);
                if (!bResult) return false;
            }
            return bResult;
        }

        private bool Handles(Type t)
        {
            return Utility.IsTypeNoAbstract(typeof(Athena.Objects.IGlyph), t);
        }
        class ToolCommand
        {
            private string _sCommand;

            public string Command
            {
                get { return _sCommand; }
                set { _sCommand = value; }
            }

            private Bitmap _Icon;
            public Bitmap Icon
            {
                get
                {
                    return _Icon;
                }
                set
                {
                    _Icon = value;
                }
            }

            private string _Description;
            public string Description
            {
                get
                {
                    return _Description;
                }
                set
                {
                    _Description = value;
                }
            }


            public ToolCommand()
            {
                _sCommand = "-";
                _Icon = null;
            }

            /// <summary>
            /// Initializes a new instance of the ToolCommand class.
            /// </summary>
            /// <param name="sCommand"></param>
            /// <param name="icon"></param>
            /// <param name="description"></param>
            public ToolCommand(string sCommand, Bitmap icon, string description)
            {
                _sCommand = sCommand;
                _Icon = icon;
                _Description = description;
            }

            public ToolStripItem ToMenuItem()
            {
                if (_Icon == null)
                {
                    return new ToolStripSeparator();
                }
                else
                {

                    ToolStripMenuItem oItem = new ToolStripMenuItem(_sCommand, _Icon);
                    oItem.Tag = _sCommand;
                    oItem.ToolTipText = _Description;
                    oItem.ImageScaling = ToolStripItemImageScaling.None;
                    oItem.Click += new EventHandler(CommandExecute);
                    return oItem;
                }
            }

            public ToolStripItem ToToolStripButton()
            {
                if (_Icon == null)
                {
                    return new ToolStripSeparator();
                }
                else
                {
                    ToolStripButton oButton = new ToolStripButton(_sCommand, _Icon);
                    oButton.DisplayStyle = ToolStripItemDisplayStyle.Image;
                    oButton.Tag = _sCommand;
                    oButton.ImageScaling = ToolStripItemImageScaling.None;
                    oButton.ToolTipText = _Description;
                    oButton.Click += new EventHandler(CommandExecute);
                    return oButton;
                }
            }

            void CommandExecute(object sender, EventArgs e)
            {
                string sTag = "";
                if (sender is ToolStripButton)
                    sTag = (string)((ToolStripButton)sender).Tag;
                else if (sender is ToolStripMenuItem)
                    sTag = (string)((ToolStripMenuItem)sender).Tag;
                else
                    return;
                switch (sTag)
                {
                    case "Add Acetylation":
                        AddDecorator(CurrentModel.Selected, "Ac", Decorator.DecoratorStyle.Circle);
                        break;
                    case "Add Glycosylation":
                        AddDecorator(CurrentModel.Selected, "G", Decorator.DecoratorStyle.Circle);
                        break;
                    case "Add Hydroxylation":
                        AddDecorator(CurrentModel.Selected, "OH", Decorator.DecoratorStyle.Circle);
                        break;
                    case "Add Methylation":
                        AddDecorator(CurrentModel.Selected, "Me", Decorator.DecoratorStyle.Circle);
                        break;
                    case "Add Myristoylation":
                        AddDecorator(CurrentModel.Selected, "My", Decorator.DecoratorStyle.Circle);
                        break;
                    case "Add Palmytoylation":
                        AddDecorator(CurrentModel.Selected, "Pa", Decorator.DecoratorStyle.Circle);
                        break;
                    case "Add Phosphorylation":
                        AddDecorator(CurrentModel.Selected, "P", Decorator.DecoratorStyle.Circle);
                        break;
                    case "Add Prenylation":
                        AddDecorator(CurrentModel.Selected, "Pr", Decorator.DecoratorStyle.Circle);
                        break;
                    case "Add Protonation":
                        AddDecorator(CurrentModel.Selected, "H", Decorator.DecoratorStyle.Circle);
                        break;
                    case "Add Sulfation":
                        AddDecorator(CurrentModel.Selected, "S", Decorator.DecoratorStyle.Circle);
                        break;
                    case "Add Ubiquitination":
                        AddDecorator(CurrentModel.Selected, "Ub", Decorator.DecoratorStyle.Circle);
                        break;
                    case "Add Unit of Information: RNA":
                        AddDecorator(CurrentModel.Selected, "mt:rna", Decorator.DecoratorStyle.Rectangle);
                        break;
                    case "Add Unit of Information: DNA":
                        AddDecorator(CurrentModel.Selected, "mt:dna", Decorator.DecoratorStyle.Rectangle);
                        break;
                    case "Add Unit of Information: Protein":
                        AddDecorator(CurrentModel.Selected, "mt:prot", Decorator.DecoratorStyle.Rectangle);
                        break;
                    case "Add Unit of Information: Psac":
                        AddDecorator(CurrentModel.Selected, "mt:psac", Decorator.DecoratorStyle.Rectangle);
                        break;
                    default:
                        break;
                }
            }

            private void AddDecorator(List<IDrawable> list, string p, Decorator.DecoratorStyle decoratorStyle)
            {
                foreach (IDrawable drawable in list)
                {
                    if (!(drawable is IGlyph)) continue;
                    IGlyph glyph = (IGlyph)drawable;
                    Decorator oDecorator = new Decorator();
                    oDecorator.Style = decoratorStyle;
                    oDecorator.Text = p;
                    
                    oDecorator.TextV = IDrawable.VerticalAlignment.Middle;
                    oDecorator.TextH = IDrawable.HorizontalAlignment.Center;
                    
                    if (decoratorStyle == Decorator.DecoratorStyle.Circle)
                        oDecorator.Dimensions = new SizeF(20f, 20f);
                    else
                        oDecorator.Dimensions = new SizeF(40f, 20f);
                    oDecorator.Location = new PointF(drawable.Location.X + drawable.Dimensions.Width / 2f, drawable.Location.Y - 10f);
                    oDecorator.ParentGlyph = (IGlyph)drawable;
                    oDecorator.EdgeThickness = glyph.EdgeThickness;
                    oDecorator.EdgeColor = glyph.EdgeColor;

                    oDecorator.AnchoredSource = drawable;
                    CurrentModel.Drawables.Add(oDecorator);
                }
                Utility.Refresh();
            }
        }

        static ToolCommand[] _oCommands = new ToolCommand[]
        {
            new ToolCommand("Add Acetylation", new Bitmap(20,20), "Adds Acetylation Decorator"),
            new ToolCommand("Add Glycosylation", new Bitmap(20,20), "Add Glycosylation Decorator"),
            new ToolCommand("Add Hydroxylation", new Bitmap(20,20), "Add Hydroxylation Decorator"),
            new ToolCommand("Add Methylation", new Bitmap(20,20), "Add Methylation Decorator"),
            new ToolCommand("Add Myristoylation", new Bitmap(20,20), "Add Myristoylation Decorator"),
            new ToolCommand("Add Palmytoylation", new Bitmap(20,20), "Add Palmytoylation Decorator"),
            new ToolCommand("Add Phosphorylation", new Bitmap(20,20), "Add Phosphorylation Decorator"),
            new ToolCommand("Add Prenylation", new Bitmap(20,20), "Add Prenylation Decorator"),
            new ToolCommand("Add Protonation", new Bitmap(20,20), "Add Protonation Decorator"),
            new ToolCommand("Add Sulfation", new Bitmap(20,20), "Add Sulfation Decorator"),
            new ToolCommand("Add Ubiquitination", new Bitmap(20,20), "Add Ubiquitination Decorator"),
            new ToolCommand(), 
            new ToolCommand("Add Unit of Information: RNA", new Bitmap(20,20), "Add RNA Decorator."),
            new ToolCommand("Add Unit of Information: DNA", new Bitmap(20,20), "Add DNA Decorator."),
            new ToolCommand("Add Unit of Information: Protein", new Bitmap(20,20), "Add Protein Decorator."),
            new ToolCommand("Add Unit of Information: Psac", new Bitmap(20,20), "Add Polysaccharide Decorator."),
        };

        private static DecorateTool _oInstance = new DecorateTool();
        public static DecorateTool Instance
        {
            get { return _oInstance; }
        }

        private DecorateTool()
        {
            // no items to put into global tool window
            _bHasMenuItems = false;
            // has items to put into context menu
            _bHasContextMenuItems = true;
            // needs a separate toolstrip for the arrange actions
            _bRequiresNewToolWindow = false;


            // register with main instance
            ToolManager.Instance.RegisterTool("Decorate Tool", "Decorates a glyph with Covalent Modification / Unit of Information.", this);
        }


        public override void SetupToolStrip(ToolStrip oStrip)
        {
            foreach (ToolCommand command in _oCommands)
            {
                oStrip.Items.Add(command.ToToolStripButton());
            }
        }
        public override void SetupContextMenu(ToolStripMenuItem oStrip)
        {
            foreach (ToolCommand command in _oCommands)
            {
                oStrip.DropDownItems.Add(command.ToMenuItem());
            }
        }

    }
}
